package com.zzy.filter;

import java.sql.*;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;



/**
 * <b>Description:用以mysql中json格式的字段，进行转换的自定义转换器，转换为实体类的T类型 属性</b>
 * <br><b>ClassName:</b> GenericTypeHandler
 * <br><b>Date:</b> 2019年2月17日 下午4:25:07
 * <br>@author <b>jianb.jiang</b>
 *
 * 1、@MappedTypes注解中的类代表此转换器可以自动转换为的java对象，@MappedJdbcTypes注解中设置的是对应的jdbctype，mysql的json对象对应的jdbctype为VARCHAR。
 *
 * 2、spring boot配置中开启typeHandler包路径的自动扫描配置：
 *
 * mybatis.type-handlers-package=com.shikuai.dao.handler
 *
 * 3、使用上，只需在pojo的属性中定义需要自动转换的java对象属性，如@MappedTypes注解中的CustomerAddressJson，在订单的pojo中有一个属性：

 */
@MappedTypes(value = {JSONObject.class, Blob.class})
@MappedJdbcTypes(value = {JdbcType.VARCHAR}, includeNullJdbcType = true)
public class GenericTypeHandler<T extends Object> extends BaseTypeHandler<T> {

    private Class<T> clazz;

    public GenericTypeHandler(Class<T> clazz) {
        if (clazz == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.clazz = clazz;
    }

    /**
     * 设置非空参数
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JSON.toJSONString(parameter));
    }

    /**
     * 根据列名，获取可以为空的结果
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String sqlJson = rs.getString(columnName);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson, clazz);
        }
        return null;
    }

    /**
     * 根据列索引，获取可以为空的结果
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String sqlJson = rs.getString(columnIndex);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson, clazz);
        }
        return null;
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String sqlJson = cs.getString(columnIndex);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson, clazz);
        }
        return null;
    }
}
